﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using SkiaSharp;

namespace Best.SmartCms.Utility
{
    /// <summary>
    /// 处理图片
    /// </summary>
    public class ImageHelper
    {
        /// <summary>
        /// 图片压缩后的宽度
        /// </summary>
        public int ResizeWith { get; set; }
        /// <summary>
        /// 图片压缩后的高度
        /// </summary>
        public int ResizeHeight { get; set; }
        /// <summary>
        /// 压缩之后的占比 如果此属性赋值优先使用
        /// </summary>
        public int ResizePercent { get; set; }
        /// <summary>
        /// 字体名称
        /// </summary>
        public string FontName { get; set; }
        /// <summary>
        /// 字大小
        /// </summary>
        private int _fontSize;

        /// <summary>
        /// 是否需要分行
        /// </summary>
        private int _textRowCount;

        /// <summary>
        /// 
        /// </summary>
        public ImageHelper(string fontName,int fontSize) : this(72, fontName,fontSize)
        {

        }

        public ImageHelper(int percent, string fontName,int fontSize)
        {
            this.ResizePercent = percent;
            this.FontName = fontName;
            this._fontSize = fontSize;
        }
        public ImageHelper(int imageWidth, int imageHeight, string fontName)
        {
            this.ResizeWith = imageWidth;
            this.ResizeHeight = imageHeight;
            this.FontName = fontName;
            this._fontSize = 15;
        }

        /// <summary>
        /// 写入字符串列
        /// </summary>
        /// <param name="image"></param>
        /// <param name="text"></param>
        /// <returns></returns>
        public MemoryStream DrawingStringListToImage(Stream image, List<string> text)
        {
            using (SKManagedStream imageManagedStream = new SKManagedStream(image,true))
            {
                var skBitmap = SKBitmap.Decode(imageManagedStream);
                //按比例缩放字体大小
                ChoiseFountSize(skBitmap.Width);
                var maxLength = text.Max(item => item.Length);
                skBitmap = ResizeImage(skBitmap, maxLength,text.Count);
                var msg = GetTextsPoint(skBitmap, text, out var wordColor);
                using (var canvas = new SKCanvas(skBitmap))
                {
                    var typeface = GetSKTypeface();
                    foreach (var imageInfo in msg)
                    {
                        var key = Encoding.UTF8.GetBytes(imageInfo.Key);
                        using (var paint = new SKPaint())
                        {
                            paint.Color = wordColor;
                            paint.TextSize = this._fontSize;
                            paint.Typeface = typeface;
                            canvas.DrawText(key, imageInfo.Value.X, imageInfo.Value.Y, paint);
                        }
                    }

                    MemoryStream returnImag = new MemoryStream();
                    canvas.Save();
                    var skImage = SKImage.FromBitmap(skBitmap);
                    skImage.Encode(SKEncodedImageFormat.Jpeg, 85).SaveTo(returnImag);
                    returnImag.Position = 0;
                    return returnImag;
                }
            }
        }

        private void ChoiseFountSize(int picWidth)
        {
            //基准宽度使用900,fontSize 30,按比例增大
            var ratio = (float)picWidth / 900;
            var reSize = Math.Round(this._fontSize * ratio);
            reSize = reSize < 1 ? 1 : reSize;
            this._fontSize = (int) reSize;

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="image"></param>
        /// <param name="text"></param>
        /// <returns></returns>
        public MemoryStream DrawingStringToImage(Stream image, string text)
        {
            using (SKManagedStream imageManagedStream = new SKManagedStream(image,true))
            {
                var skBitmap = SKBitmap.Decode(imageManagedStream);
                var msg = GetTextPoint(skBitmap, text);
                var canvas = new SKCanvas(skBitmap);
                var typeface = GetSKTypeface();
                foreach (var imageInfo in msg)
                {
                    using (var paint = new SKPaint())
                    {
                        paint.Color = new SKColor(255, 0, 0);
                        paint.TextSize = this._fontSize;
                        paint.Typeface = typeface;
                        canvas.DrawText(imageInfo.Key, imageInfo.Value.X, imageInfo.Value.Y, paint);
                    }
                }

                MemoryStream returnImag = new MemoryStream();
                canvas.Save();
                var skImage = SKImage.FromBitmap(skBitmap);
                skImage.Encode(SKEncodedImageFormat.Jpeg, 85).SaveTo(returnImag);
                returnImag.Position = 0;
                return returnImag;
            }
        }

        /// <summary>
        /// 重置图片高宽
        /// </summary>
        /// <param name="image"></param>
        /// <param name="textLen"></param>
        /// <param name="textCount"></param>
        /// <returns></returns>
        private SKBitmap ResizeImage(SKBitmap image, int textLen,int textCount)
        {
            int height = image.Height;
            int width = image.Width;
            var wordLen = textLen * this._fontSize;
            if (width < (wordLen + this._fontSize * 2))
            {
                width = wordLen + this._fontSize * 2;

            }

            if (height < _fontSize * 5 + this._fontSize * textCount)
            {
                height = _fontSize * 5 + this._fontSize * textCount;
            }

            if (height != image.Height || width != image.Width)//判断是否需要重置大小
            {
                image = image.Resize(new SKImageInfo(width, height), SKBitmapResizeMethod.Lanczos3);
            }
            return image;
        }

        /// <summary>
        /// 获取起始点位置
        /// </summary>
        /// <param name="image"></param>
        /// <param name="texts"></param>
        /// <param name="wordcolor"></param>
        /// <returns></returns>
        private Dictionary<string, ImageInfo> GetTextsPoint(SKBitmap image, List<string> texts,out SKColor wordcolor)
        {
            
            int weight = image.Width;
            var listY = new List<int>();
            Dictionary<string, ImageInfo> dic = new Dictionary<string, ImageInfo>();
            var textIndex = 1;
            foreach (var text in texts)
            {
                var y = _fontSize + (int)(_fontSize * 1.2 * textIndex);
                    dic.Add(text, new ImageInfo()
                    {
                        X = this._fontSize,
                        Y = y
                    });
                listY.Add(y);
                textIndex++;
            }

            //获取背景颜色
            var rEve = 0;
            var gEve = 0;
            var bEve = 0;
            var count = 0;
            for (var x = 0; x < weight; x= x+weight/20)
            {
               listY.ForEach(y =>
               {
                   var pixrgb = image.GetPixel(x, y);
                   rEve = pixrgb.Red+ rEve;
                   gEve = pixrgb.Green + gEve;
                   bEve = pixrgb.Blue+ bEve;
                   count++;
               });   
            }
            var red = rEve / count;
            var green = gEve / count;
            var blue = bEve / count;
            wordcolor = red * 0.299 + green * 0.578 + blue * 0.114 >= 160 ? new SKColor(65, 105, 225) : new SKColor(222, 222, 222);

            return dic;
        }

        private Dictionary<string, ImageInfo> GetTextPoint(SKBitmap image, string text)
        {
            Dictionary<string, ImageInfo> dic = new Dictionary<string, ImageInfo>();
            int height = image.Height;
            int width = image.Width;
            if (this._textRowCount < 2)
            {
                dic.Add(text, new ImageInfo()
                {
                    X = width - text.Length * this._fontSize - this._fontSize,
                    Y = height - this._fontSize
                });
            }
            else
            {
                int len = ((width - this._fontSize * 2) / this._fontSize);
                for (int i = 0; i < this._textRowCount; i++)
                {
                    var startIndex = i * len;
                    var suben = len;
                    if ((startIndex + len - 1) > text.Length)
                    {
                        suben = text.Length - startIndex;
                    }
                    dic.Add(text.Substring(startIndex, suben), new ImageInfo()
                    {
                        X = width - len * this._fontSize - this._fontSize,
                        Y = height - this._fontSize - (this._textRowCount - i) * this._fontSize
                    });
                }
            }
            return dic;
        }
        private SKTypeface GetSKTypeface()
        {
            if (string.IsNullOrEmpty(this.FontName))
            {
                return SKTypeface.FromFamilyName(this.FontName, SKTypefaceStyle.Normal);
            }

            if (this.FontName.Contains("."))
            {
                return SKTypeface.FromFile(Path.Combine(AppContext.BaseDirectory, "Fonts", this.FontName));
            }
            return SKTypeface.FromFamilyName(this.FontName, SKTypefaceStyle.Normal);
        }
        sealed class ImageInfo
        {
            public int X { get; set; }
            public int Y { get; set; }
        }

    }
}
